package edu.hubu.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import edu.hubu.annotations.FilterField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import net.moon.annotation.FieldIgnore;
import net.moon.jpa.model.BaseEntity;
import org.hibernate.annotations.Proxy;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import java.io.Serializable;
import java.util.*;

/**
 * @author moonlan
 * @date 2020/10/18 上午10:10
 */
@Entity
@Table(name = "user")
//逻辑删除注解，删除sql变成了update
@SQLDelete(sql = "update user set user_is_deleted = true where user_sid = ?")
//where条件带上了逻辑删除条件
@Where(clause = "user_is_deleted = false")
@ApiModel("用户类")
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"})
@EntityListeners(AuditingEntityListener.class)
@Inheritance(strategy = InheritanceType.JOINED)
@Proxy(lazy = false)
public class User extends BaseEntity implements Serializable {
    @Id
    @Column(name = "user_sid")
    @ApiModelProperty(value = "用户工号", position = 1)
    private String userSid;

    @Column(name = "user_name")
    @ApiModelProperty(value = "用户姓名", position = 2)
    protected String userName;

    @Column(name = "user_password")
    @ApiModelProperty(value = "用户密码", position = 3)
    @FieldIgnore
    protected String userPassword;

    @Column(name = "user_telephone_number")
    @ApiModelProperty(value = "用户电话号码", position = 8)
    @FieldIgnore
    protected String userTelephoneNumber;

    @Column(name = "user_effective_date")
    @ApiModelProperty(value = "用户帐号生效时间", position = 9)
    @CreatedDate
    @FieldIgnore
    protected Date userEffectiveDate;

    @Column(name = "user_expiry_date")
    @ApiModelProperty(value = "用户帐号失效时间", position = 10)
    @FieldIgnore
    protected Date userExpiryDate;

    @Column(name = "user_api_key")
    @ApiModelProperty(value = "用户Apikey", position = 11)
    @FieldIgnore
    protected String userApiKey;

    @Column(name = "user_api_key_expiry_date")
    @ApiModelProperty(value = "用户Apikey失效时间", position = 12)
    @FieldIgnore
    protected Date userApiKeyExpiryDate;

    @Column(name = "user_photo_url")
    @ApiModelProperty(value = "用户头像url", position = 13)
    protected String userPhotoUrl;

    @Column(name = "user_is_forbidden")
    @ApiModelProperty(value = "用户是否被禁用", position = 14)
    private boolean userIsForbidden = false;

    @Column(name = "user_is_deleted")
    @ApiModelProperty(value = "用户是否被删除", position = 15)
    private boolean userIsDeleted = false;

//    @OneToOne(targetEntity = Token.class, cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
//    @JoinColumn(name = "user_token_id", referencedColumnName = "token_id")
    @OneToOne(mappedBy = "user", fetch = FetchType.LAZY)
    @JsonIgnore
    private Token token;

//    @ManyToMany(targetEntity = Role.class, cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
//    @JoinTable(name = "user_role", joinColumns = {@JoinColumn(name = "user_role_user_sid", referencedColumnName = "user_sid")}, inverseJoinColumns = @JoinColumn(name = "user_role_role_id", referencedColumnName = "role_id"))
//    @ApiModelProperty(hidden = true)
//    protected List<Role> roles = new ArrayList<>();
    @ManyToOne(targetEntity = Role.class, cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
    @JoinColumn(name = "user_role_id", referencedColumnName = "role_id")
    protected Role role;

    public Role getRole() {
        return role;
    }

    public User setRole(Role role) {
        this.role = role;
        return this;
    }

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    protected List<Announcement> announcements = new ArrayList<>();

    public User() {
        String s = "USER" + "-" + Calendar.getInstance().get(Calendar.YEAR);
        Random random = new Random();
        int i = 100000000 + random.nextInt(10000000) + 1;
        userSid = s + "-" + i;
    }

    public User(String userSid, String userName, String userPassword, String userTelephoneNumber, Date userEffectiveDate, Date userExpiryDate, String userApiKey, Date userApiKeyExpiryDate, String userPhotoUrl, boolean userIsForbidden, boolean userIsDeleted, Token token, List<Token> tokens, List<Role> roles, List<Announcement> announcements) {
        this.userSid = userSid;
        this.userName = userName;
        this.userPassword = userPassword;
        this.userTelephoneNumber = userTelephoneNumber;
        this.userEffectiveDate = userEffectiveDate;
        this.userExpiryDate = userExpiryDate;
        this.userApiKey = userApiKey;
        this.userApiKeyExpiryDate = userApiKeyExpiryDate;
        this.userPhotoUrl = userPhotoUrl;
        this.userIsForbidden = userIsForbidden;
        this.userIsDeleted = userIsDeleted;
        this.token = token;
        this.announcements = announcements;
    }

    public static UserBuilder builder() {
        return new UserBuilder();
    }

    public String getUserSid() {
        return userSid;
    }

    public User setUserSid(String userSid) {
        this.userSid = userSid;
        return this;
    }

    public String getUserName() {
        return userName;
    }

    public User setUserName(String userName) {
        this.userName = userName;
        return this;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public User setUserPassword(String userPassword) {
        this.userPassword = userPassword;
        return this;
    }

    public String getUserTelephoneNumber() {
        return userTelephoneNumber;
    }

    public User setUserTelephoneNumber(String userTelephoneNumber) {
        this.userTelephoneNumber = userTelephoneNumber;
        return this;
    }

    public Date getUserEffectiveDate() {
        return userEffectiveDate;
    }

    public User setUserEffectiveDate(Date userEffectiveDate) {
        this.userEffectiveDate = userEffectiveDate;
        return this;
    }

    public Date getUserExpiryDate() {
        return userExpiryDate;
    }

    public User setUserExpiryDate(Date userExpiryDate) {
        this.userExpiryDate = userExpiryDate;
        return this;
    }

    public String getUserApiKey() {
        return userApiKey;
    }

    public User setUserApiKey(String userApiKey) {
        this.userApiKey = userApiKey;
        return this;
    }

    public Date getUserApiKeyExpiryDate() {
        return userApiKeyExpiryDate;
    }

    public User setUserApiKeyExpiryDate(Date userApiKeyExpiryDate) {
        this.userApiKeyExpiryDate = userApiKeyExpiryDate;
        return this;
    }

    public String getUserPhotoUrl() {
        return userPhotoUrl;
    }

    public User setUserPhotoUrl(String userPhotoUrl) {
        this.userPhotoUrl = userPhotoUrl;
        return this;
    }

    public boolean isUserIsForbidden() {
        return userIsForbidden;
    }

    public User setUserIsForbidden(boolean userIsForbidden) {
        this.userIsForbidden = userIsForbidden;
        return this;
    }

    public boolean isUserIsDeleted() {
        return userIsDeleted;
    }

    public User setUserIsDeleted(boolean userIsDeleted) {
        this.userIsDeleted = userIsDeleted;
        return this;
    }

    public Token getToken() {
        return token;
    }

    public User setToken(Token token) {
        this.token = token;
        return this;
    }

    public List<Announcement> getAnnouncements() {
        return announcements;
    }

    public User setAnnouncements(List<Announcement> announcements) {
        this.announcements = announcements;
        return this;
    }

    public static class UserBuilder {
        private String userSid;
        private String userName;
        private String userPassword;
        private String userTelephoneNumber;
        private Date userEffectiveDate;
        private Date userExpiryDate;
        private String userApiKey;
        private Date userApiKeyExpiryDate;
        private String userPhotoUrl;
        private boolean userIsForbidden;
        private boolean userIsDeleted;
        private Token token;
        private List<Token> tokens;
        private List<Role> roles;
        private List<Announcement> announcements;

        UserBuilder() {
        }

        public UserBuilder userSid(String userSid) {
            this.userSid = userSid;
            return this;
        }

        public UserBuilder userName(String userName) {
            this.userName = userName;
            return this;
        }

        public UserBuilder userPassword(String userPassword) {
            this.userPassword = userPassword;
            return this;
        }

        public UserBuilder userTelephoneNumber(String userTelephoneNumber) {
            this.userTelephoneNumber = userTelephoneNumber;
            return this;
        }

        public UserBuilder userEffectiveDate(Date userEffectiveDate) {
            this.userEffectiveDate = userEffectiveDate;
            return this;
        }

        public UserBuilder userExpiryDate(Date userExpiryDate) {
            this.userExpiryDate = userExpiryDate;
            return this;
        }

        public UserBuilder userApiKey(String userApiKey) {
            this.userApiKey = userApiKey;
            return this;
        }

        public UserBuilder userApiKeyExpiryDate(Date userApiKeyExpiryDate) {
            this.userApiKeyExpiryDate = userApiKeyExpiryDate;
            return this;
        }

        public UserBuilder userPhotoUrl(String userPhotoUrl) {
            this.userPhotoUrl = userPhotoUrl;
            return this;
        }

        public UserBuilder userIsForbidden(boolean userIsForbidden) {
            this.userIsForbidden = userIsForbidden;
            return this;
        }

        public UserBuilder userIsDeleted(boolean userIsDeleted) {
            this.userIsDeleted = userIsDeleted;
            return this;
        }

        public UserBuilder token(Token token) {
            this.token = token;
            return this;
        }

        public UserBuilder tokens(List<Token> tokens) {
            this.tokens = tokens;
            return this;
        }

        public UserBuilder roles(List<Role> roles) {
            this.roles = roles;
            return this;
        }

        public UserBuilder announcements(List<Announcement> announcements) {
            this.announcements = announcements;
            return this;
        }

        public User build() {
            return new User(userSid, userName, userPassword, userTelephoneNumber, userEffectiveDate, userExpiryDate, userApiKey, userApiKeyExpiryDate, userPhotoUrl, userIsForbidden, userIsDeleted, token, tokens, roles, announcements);
        }

        public String toString() {
            return "User.UserBuilder(userSid=" + this.userSid + ", userName=" + this.userName + ", userPassword=" + this.userPassword + ", userTelephoneNumber=" + this.userTelephoneNumber + ", userEffectiveDate=" + this.userEffectiveDate + ", userExpiryDate=" + this.userExpiryDate + ", userApiKey=" + this.userApiKey + ", userApiKeyExpiryDate=" + this.userApiKeyExpiryDate + ", userPhotoUrl=" + this.userPhotoUrl + ", userIsForbidden=" + this.userIsForbidden + ", userIsDeleted=" + this.userIsDeleted + ", token=" + this.token + ", tokens=" + this.tokens + ", roles=" + this.roles + ", announcements=" + this.announcements + ")";
        }
    }
}
